<template>
  <div class="product-edit-form">
    <form-builder ref="form" :fields="productFields" :value="value" mode="product" @update="update" class="product-type-select">
      <template slot="template" slot-scope="{field}">
        <form-item :label="field.displayName">
          <base-select
            :showOnBottom='field.showOnBottom'
            v-model="value.template"
            :remote-method="searchTemplate"
            @input="updateTemplate"
          >

            <div class="product-template-option" slot="option" slot-scope="{option}">
              <h3>{{option.name}}</h3>
              <p>
                <span><label>产品编号：</label><span>{{option.serialNumber}}</span></span>
                <span><label>产品类型：</label><span>{{option.type}}</span></span>
              </p>
            </div>

          </base-select>

        </form-item>
      </template>
      <!-- TODO: copy ProductEditFormV2组件的产品类型代码 -->
      <template slot="catalogId" slot-scope="{ field }">
        <form-item :label="field.displayName" :validation='validationCatalog'>
          <form-cascader :field='field' :tree='catalogTree' version='new' :value='catalog' :remote-search="true" @input='catalogInput' @beforeFilter="beforeFilter"></form-cascader>
        </form-item>
      </template>
      <template slot="customer" slot-scope="{field}" v-if="!customerIsReadonly">
        <form-item :label="field.displayName" validation>
          <customer-select v-model="value.customer" :field="customerField" :remote-method="searchCustomer" :update-customer="updateCustomer" placeholder="请输入关键字搜索客户"></customer-select>
        </form-item>
        <form-item label="联系人" :is-not-null="field.setting.customerOption.linkmanNotNull" v-if="field.setting.customerOption && field.setting.customerOption.linkman">
          <form-customer-select v-model="value.linkman" :field="getField('linkman', customerField)" :remote-method="searchCustomerLinkman" :update-linkman="updateLinkman" @createInfo="createInfo" type="linkman" placeholder="请先选择客户"></form-customer-select>
        </form-item>
        <form-item label="地址" :is-not-null="field.setting.customerOption.addressNotNull" v-if="field.setting.customerOption && field.setting.customerOption.address">
          <form-customer-select-address v-model="value.customerAddress" :field="getField('productAddress', customerField)" :remote-method="searchCustomerAddress" :update-customer-address="updateCustomerAddress" @createInfo="createInfo" type="address" placeholder="请先选择客户"></form-customer-select-address>
        </form-item>
      </template>

      <template slot="serialNumber" slot-scope="{field}">
        <form-item :label="field.displayName">
          <form-text
            :field="field"
            :value="value.serialNumber" @update="update"
            :placeholder="genPlaceholder(field)"/>
        </form-item>
        <span class="product_error" v-if="serialNumberExist">产品编号已存在</span>
      </template>

      <!-- start 产品类型 -->
      <template slot="type" slot-scope="{field}">
        <form-item :label="field.displayName">
          <div class="input-and-btn">
            <form-select
              :field="field" 
              :source="field.setting.dataSource.map(d => {
                return {
                  text: d,
                  value: d
                }
              }) || []"
              v-model="value.type"
              :clearable="false"
              :placeholder="genPlaceholder(field)"/>
          </div>
        </form-item>
      </template>
      <!-- end 产品类型 -->

    </form-builder>
    <edit-contact-dialog ref="EditContactDialog" :customer="customer" @updateLinkman="updateLinkman" />
    <edit-address-dialog ref="EditAddressDialog" :customer-id="customerId" @updateCustomerAddress="updateCustomerAddress" />
    <!-- :default-address="selectedAddress" -->
  </div>
</template>

<script>
import * as FormUtil from '@src/component/form/util';
import FormMixin from '@src/component/form/mixin/form'

// import {searchCustomer} from '@src/api/EcSearchApi.js';
import { checkSerialNumber, getProductTemplateList, searchCustomerAddressForProduct} from '@src/api/ProductApi';
import { cloneData, queryCatalogTree } from "@src/api/ProductV2Api";
import { getCustomerList } from '@src/api/CustomerApi'
import _ from 'lodash'

import EditContactDialog from './EditContactDialog.vue';
import EditAddressDialog from './EditAddressDialog.vue'
import { formatAddress } from 'pub-bbx-utils';
import { hasBSCEnterpriseEdition } from '@src/util/version';
export default {
  name: 'product-edit-form',
  props: {
    fields: {
      type: Array,
      default: () => ([]),
    },
    value: {
      type: Object,
      required: true
    },
    productId: {
      type: String,
      default: ''
    },
    customerIsReadonly: {
      type: Boolean,
      default: false,
    }
  },
  inject: ['initData'],
  data() {
    return {
      validation: this.buildValidation(),
      template: [],
      serialNumberExist: false,
      catalog:[],
      catalogTree:[],
    }
  },
  computed: {
    productFields() {
      // 服务云企业版产品列表隐藏产品模版字段
      if(hasBSCEnterpriseEdition()) {
        return this.fields.filter(item=> item.fieldName != 'template')
      }
      return this.fields
    },
    customerField() {
      return this.fields.filter(f => f.fieldName === 'customer')[0]
    },

    isPhoneUnique() {
      return this.initData.isPhoneUnique || false;
    },
    customer() {
      let customer = (this.value.customer && this.value.customer[0]) || {};
      if(!customer.id && customer.value) {
        customer.id = customer.value;
      }
      return customer || {};
    },
    customerId() {
      return (this.customer && (this.customer.id || this.customer.value)) || '';
    }
  },
  mounted(){
    const existCatalog = this.fields.find(item => item.fieldName === 'catalogId');
    if(existCatalog) this.getTreeList();
  },
  methods: {
    // 产品类型远程搜索
    beforeFilter: _.debounce(async function (value) {
      if (!value) return this.getTreeList();
      try {
        const { code, message, result } = await queryCatalogTree({ keyWord: value });
        if (code === 0) {
          this.deleteEmpty(result);
          this.catalogTree = result;
          this.initCatalog();
        } else {
          this.$platform.notification({
            type: 'error',
            message: message
          })
        }
      } catch (err) {
        console.error(err);
      }
    }, 500),

    getField(tag, field) {
      let tv = Object.assign({}, field);
      tv.fieldName = tag;
      tv.formType = 'extend';
      tv.displayName = tag == 'linkman' ? '联系人' : '地址';
      tv.isNull = tag == 'linkman' ? !tv.setting.customerOption.linkmanNotNull : !tv.setting.customerOption.addressNotNull

      return tv;
    },
    validationCatalog() {
      const catalogIdItem = this.fields.find(item => item.fieldName === 'catalogId');
      let isNull = catalogIdItem?.isNull
      return new Promise((resolve, reject) => {
        if(!this.catalog.length && isNull == 0) {
          return resolve('请选择产品类型');
        } 
        resolve(null);
      })
    },
    catalogInput(value) {
      const length = value.length;
      this.catalog = value;
      const field = this.fields.find(item => item.fieldName === 'catalogId');
      this.update({
        field,
        newValue:{
          id: length ? value[length - 1] : '',
        }
      })
    },
    initCatalog() {
      const keys = Object.keys(this.value);
      const catalogKey = keys.find(key=> key === 'catalogId');
      if(catalogKey) {
        const catalogId = this.value[catalogKey];
        const id = Array.isArray(catalogId) ? catalogId[0]?.id : catalogId.id;
        let treeArr = [];
        this.flat(this.catalogTree, treeArr);
        if(id) this.getCatalogParents(id, treeArr, this.catalog);
      }
    },
    // 拉平产品类型树
    flat(tasks,arr) {
      tasks.forEach(item => {
        arr.push(item);
        if(item.tasks && item.tasks.length){
          this.flat(item.tasks, arr);
        }
      });
    },
    // 获取产品类型id及其父级
    getCatalogParents(id, treeArr, catalogArr){
      catalogArr.unshift(id);
      // vip及标准版产品类型只有一层，所以取值时不取父类型，否则编辑时，对于原先多层的类型会匹配失败，导致类型没有显示
      if (this.initData.openSuperCodePro === false) return
      const item = treeArr.find(t=> t.id === id);
      if(item && item.parentId){
        this.getCatalogParents(item.parentId, treeArr, catalogArr);
      }
    },
    async getTreeList(){
      try{
        const {code, message, result} = await cloneData();
        if(code === 0) {
          this.deleteEmpty(result);
          this.catalogTree = result;
          this.initCatalog();
        } else {
          this.$platform.notification({
            type: 'error',
            title: '请求错误',
            message: message
          })
        }
      } catch(err) {
        console.error(err);
      }
    },
    // 删除空子集
    deleteEmpty(list){
      list.forEach(item => {
        if(!item.tasks.length){
          delete item.tasks;
        } else {
          this.deleteEmpty(item.tasks);
        }
      });
    },
    updateTemplate(value) {
      let nv = null;
      const template = value[0];
      
      this.fields.forEach(f => {
        nv = f.isSystem ? template[f.fieldName] : template.attribute[f.fieldName];
        if(f.fieldName === 'catalogId') {
          const { catalogId, type } = template
          nv = {
            id: catalogId,
            catalogName: type,
            pathName: type, // 接口没有完整的pathName，暂时取type值
            type
          }
        }

        if (f.formType === 'address') {
          console.log(nv)
        }

        if (!!nv && f.fieldName != 'customer' && f.fieldName != 'template') {
          this.update(({
            field: f,
            newValue: nv
          }))
        }
      });
    },
    buildValidation(){
      const serialNumberUnique = this.initData.productConfig.serialNumberUnique;

      let checkSerialNumberFn = _.debounce(function(params, resolve, changeStatus){

        if (!params.serialNumber) return resolve(null) ;

        changeStatus(true);
        return checkSerialNumber(params).then(res => {
          changeStatus(false);
          return resolve(res.error ? res.error : null);
        })
          .catch(err => console.error(err))
      }, 500)

      const that = this;

      return Object.freeze({

        serialNumber: !serialNumberUnique ? true : function(value, field, changeStatus){
          let params = {
            id: that.productId || '',
            serialNumber: value
          }

          return new Promise((resolve, reject) => checkSerialNumberFn(params, resolve, changeStatus))
        }
      });
    },

    genPlaceholder(field){
      return FormUtil.genPlaceholder(field)
    },

    update({field, newValue, oldValue}){
      let { fieldName, displayName, formType } = field;
      if (this.$appConfig.debug) {
        console.info(`[FormBuilder] ${displayName}(${fieldName}) : ${JSON.stringify(newValue)}`);
      }
      if(fieldName==='serialNumber'){
        if(newValue){
          checkSerialNumber({id:this.productId,serialNumber:newValue}, false).then(res=>{
            if(res.hasOwnProperty('ok')){
              this.serialNumberExist=false;
            }else{
              this.serialNumberExist=true;
            }
          })
        }else{
          this.serialNumberExist=false;
        }
      } else if(fieldName === 'catalogId' && this.catalogTree) {
        this.catalog = this.searchCatalogIds(this.catalogTree, newValue.id) || []
      }
      let value = this.value;

      this.$set(value, fieldName, newValue);
      this.$emit('input', value);
    },
    // 在产品类型选项中查找对应的值
    searchCatalogIds(catalogOption, catalogId) {
      for(let catalog of catalogOption) {
        if(catalog.tasks) {
          // 递归寻找值
          let res = this.searchCatalogIds(catalog.tasks, catalogId)
          // 子级找到值，就把这级的id加进去
          if (res) {
            res.unshift(catalog.id)
            return res
          }
        } else if (catalog.id === catalogId) {
          // 找到值并返回
          return [catalogId]
        }
      }
    },
    updateCustomer(value) {
      const cf = this.fields.filter(f => f.fieldName === 'customer')[0];
      this.update({
        field: cf,
        newValue: value
      })
      this.fetchCustomer(value);
    },
    updateLinkman(value) {      
      let field = {
        fieldName: 'linkman',
        displayName: '联系人'
      }
      this.update({
        field,
        newValue: value
      })
      this.fetchLinkmanAddress(value);
    },
    updateCustomerAddress(value) {
      let field = {
        fieldName: 'customerAddress',
        displayName: '地址'
      }
      this.update({
        field,
        newValue: value
      })
    },
    clearLinkman() {
      let field = {
        fieldName: 'linkman',
        displayName: '联系人'
      }
      this.update({
        field,
        newValue: []
      })
    },
    clearCustomerAddress() {
      let field = {
        fieldName: 'customerAddress',
        displayName: '地址'
      }
      this.update({
        field,
        newValue: []
      })
    },
    validate() {
      return this.$refs.form.validate(false)
        .then(valid => {
          return valid
        })
        .catch(err => console.error(err))
    },
    searchCustomer(params) {
      // params has three properties include keyword、pageSize、pageNum.
      const pms = params || {};

      return getCustomerList(pms)
        .then(res => {
          if (!res || !res.list) return;
          if (res.list) {
            res.list = res.list.map(customer => Object.freeze({
              id: customer.id,
              label: customer.name,
              value: customer.id,
              lmPhone: customer.lmPhone,
              lmName: customer.lmName,
              serialNumber: customer.serialNumber,
              customerAddress: customer.customerAddress
            }))
          }

          return res;
        })
        .catch(e => console.error(e));
    },
    fetchCustomer(params) {
      const pms = {
        customerId: params[0].id,
        notNull: true,
        productId: ''
      };
      
      this.clearLinkman();
      this.clearCustomerAddress();
      return this.$http.get('/task/defaultInfo', pms)
        .then(res => {
          if (!res) return;
          let linkman = [
            {
              label: res.linkman.name,
              value: res.linkman.id,
              phone: res.linkman.phone
            }
          ]
          this.updateLinkman(linkman);

          let address = [
            {
              label: formatAddress(res.address),
              value: res.address && res.address.id
            }
          ]
          res.address ? this.updateCustomerAddress(address) : '';

          return res;
        })
        .catch(e => console.error(e));
    },
    fetchLinkmanAddress(value) {
      let linkman = value[0];
      if (!linkman) return;
      const pms = {
        lmId: linkman.value
      };
      this.clearCustomerAddress();
      return this.$http.get('/task/getLmBindAddress', pms)
        .then(res => {
          if (!res) return;
          let address = [
            {
              label: formatAddress(res.data),
              value: res.data && res.data.id
            }
          ]
          res.data && res.data.id ? this.updateCustomerAddress(address) : '';
          return res;
        })
        .catch(e => console.error(e));
    },
    searchTemplate(params) {
      // params has three properties include keyword、pageSize、pageNum.
      const pms = params || {};

      return getProductTemplateList(pms)
        .then(res => {
          if (!res || !res.list) return;
          if (res.list) {
            res.list = res.list.map(template => Object.freeze({
              label: template.name,
              value: template.id,
              ...template
            }))
          }

          return res;
        })
        .catch(e => console.error(e));
    },
    searchCustomerLinkman (params) {
      if(!this.value.customer.length) {
        return new Promise((resolve, reject) => {
          resolve(null)
        })
      }

      const pms = params || {};
      let customer = this.value.customer[0];
      pms.customerId = customer.value;

      return this.$http.get('/customer/linkman/list', pms)
        .then(res => {
          if (!res || !res.list) return;
          if (res.list) {
            res.list = res.list.map(linkman => Object.freeze({
              label: linkman.name,
              value: linkman.id,
              phone: linkman.phone
            }))
          }

          return res;
        })
        .catch(e => console.error(e));
    },
    searchCustomerAddress (params) {
      if(!this.value.customer.length) {
        return new Promise((resolve, reject) => {
          resolve(null)
        })
      }

      const pms = params || {};
      let customer = this.value.customer[0];
      let linkman = this.value.linkman[0];
      pms.customerId = customer.value;
      // pms.linkmanId = linkman.value;

      return searchCustomerAddressForProduct(pms)
        .then(res => {
          if (!res || !res.data) return;
          if (res.data.list) {
            res.data.list = res.data.list.map(address => Object.freeze({
              label: formatAddress(address),
              value: address.id,
            }))
          }

          return res.data;
        })
        .catch(e => console.error(e));
    },
    createInfo(type) {
      if(!this.value.customer.length) {
        this.$platform.alert('请先选择客户');
        return;
      }
      if(type == 'linkman') this.$refs.EditContactDialog.openDialog();
      if(type == 'address') this.$refs.EditAddressDialog.openDialog();
    }
  },
  components: {
    [EditContactDialog.name]: EditContactDialog,
    [EditAddressDialog.name]: EditAddressDialog,

    'customer-select': {
      name: 'customer-select',
      mixins: [FormMixin],
      props: {
        value: {
          type: Array,
          default: () => []
        },
        remoteMethod: Function,
        updateCustomer: Function,
        placeholder: String,
      },
      methods: {
        input(value){
          this.$emit('input', value)
        },
      },
      
      render(h){

        return (
          <base-select
            value={this.value}
            placeholder={this.placeholder}
            remoteMethod={this.remoteMethod}
            onInput={this.updateCustomer}

            {...{
              scopedSlots: {
                option: props => {
                  return (
                    <div class="customer-item">
                      <h3>{props.option.label}</h3>
                      <p>
                        <span><label>电话：</label><span>{props.option.lmPhone}</span></span>
                        <span><label>编号：</label><span>{props.option.serialNumber}</span></span>
                        <span><label>联系人：</label><span>{props.option.lmName}</span></span>
                      </p>
                    </div>
                  );
                }
              }
            }}
          >
          </base-select>
        )
      }
    },

    'form-customer-select': {
      name: 'form-customer-select',
      mixins: [FormMixin],
      inject: ['initData'],
      props: {
        value: {
          type: Array,
          default: () => []
        },
        remoteMethod: Function,
        updateLinkman: Function,
        placeholder: String,
        type: String,
      },
      computed: {
        auth() {          
          return this.initData?.loginUser?.authorities || this.initData?.authorities;
        },
        createdPermission() {
          return this.auth.CUSTOMER_CREATE == 3;
        }
      },
      methods: {
        input(value){
          this.$emit('input', value)
        },

        createInfo(type, event) {
          this.$emit('createInfo', type);
        },

        renderBtn() {
          if(!this.createdPermission) return null;
          return (
            <el-button type="button" onClick={e => this.createInfo(this.type, e)} class="action-btn margin-left-10">新建</el-button>
          )
        }
      },
      render(h){        
        return (
          <div class="form-customer-select">
            <base-select
              value={this.value}
              placeholder={this.placeholder}
              remoteMethod={this.remoteMethod}
              onInput={this.updateLinkman}
              clearable

              {...{
                scopedSlots: {
                  label: props => {
                    let value = props.value || [];
                    let linkman = value[0] || {};
                    let nameAndPhone = `${linkman.label || ''} ${linkman.phone || ''}`
                    return (
                      <span>{ nameAndPhone }</span>
                    )
                  },
                  option: props => {
                    return (
                      <p class="customer-linkman">
                        <span><label>姓名：</label><span>{props.option.label}</span></span>
                        <span><label>电话：</label><span>{props.option.phone}</span></span>
                      </p>
                    );
                  }
                }
              }}
            />
            { this.renderBtn(h) }
          </div>
        )
      }
    },

    'form-customer-select-address': {
      name: 'form-customer-select-address',
      mixins: [FormMixin],
      inject: ['initData'],
      props: {
        value: {
          type: Array,
          default: () => []
        },
        remoteMethod: Function,
        updateCustomerAddress: Function,
        placeholder: String,
        type: String
      },
      computed: {
        auth() {          
          return this.initData?.loginUser?.authorities || this.initData?.authorities;
        },

        createdPermission() {
          return this.auth.CUSTOMER_CREATE == 3;
        },
      },
      methods: {
        input(value){
          this.$emit('input', value)
        },

        createInfo(type, event) {
          this.$emit('createInfo', type);
        },

        renderBtn() {
          if(!this.createdPermission) return null;
          return (
            <el-button type="button" onClick={e => this.createInfo(this.type, e)} class="action-btn margin-left-10">新建</el-button>
          )
        }
      },
      render(h){
        return (
          <div class="form-customer-select">
            <base-select
              value={this.value}
              placeholder={this.placeholder}
              remoteMethod={this.remoteMethod}
              onInput={this.updateCustomerAddress}
              clearable
            />
            { this.renderBtn(h) }
          </div>
        )
      }
    }

  }
}
</script>

<style lang="scss">
  .margin-left-10{
    margin-left: 10px;
  }
  .product-template-option {
    * {
      margin: 0;
    }
    padding: 10px 0;
    h3 {
      font-size: 14px;
      font-weight: 500;
      line-height: 24px;
    }


    p {
      display: flex;
      justify-content: space-between;
      line-height: 24px;

      &>span {
        width: 50%;
        display: flex;
        justify-content: flex-start;
        font-size: 12px;
        color: #666666;
        padding-right: 10px;

        &>label {
          padding: 0;
          min-width: 70px;
        }
        &>span {
          @include text-ellipsis();
        }
      }
    }
  }

  .form-item-control {
    .form-customer-select {
      display: flex;

      .base-select-container {
        flex: 1;
      }

      .btn {
        width: 60px;
        height: 32px;
        line-height: 22px;
      }
    }
  }

  .base-modal-body {
    .form-builder {
      width: 540px;
    }
  }

  .customer-item {
    h3 {
      font-size: 14px;
      margin: 0;
      padding-left: 10px;
    }

    p {
      display: flex;
      margin: 0;

      span {
        label {
          display: inline-block;
          width: auto;
        }

        span {
          margin-right: 10px;
        }
      }
    }
  }

  .customer-linkman {
    display: flex;
    margin: 0;

    span {
      label {
        display: inline-block;
        width: auto;
      }

      span {
        margin-right: 10px;
      }
    }
  }

</style>

<style lang='scss' scoped>
.product_error{
 color:#f56c6c;
 margin-left:131px;
 display:inline-block;
 transform:translateY(-8px);
 font-size:12px;
}
.product-type-select{
 width: 100%;
}
.product-type-select ::v-deep .list-wrapper { 
  height: 300px;
  overflow: hidden;
}
.product-edit-form{
 margin: 0 30px;
}
</style>
